home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 176-200 / disk_193 / zc / fun.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  11KB  |  754 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    fun.c
  12.  *
  13.  *    Handle function entry, exit, etc.
  14.  *    Parse statements.
  15.  *    Also, general syntax error recovery strategy.
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include "param.h"
  20. #include "tok.h"
  21. #include "nodes.h"
  22. #include "cookie.h"
  23.  
  24. #if MMCC
  25. overlay "pass2"
  26. #endif
  27.  
  28. extern NODE *cur;
  29.  
  30. int level;
  31. NODE *blktab;
  32. NODE *labels;
  33.  
  34. struct swittbl {
  35.     NODEP    caselist;
  36.     int    deflbl;
  37. } *curswit;
  38.  
  39. int curbrk, curcont;
  40. int funtopl, funbotl, funretl, funstrl;
  41. NODEP funtyp;
  42. int maxregs;
  43. long maxlocs;
  44.  
  45. int skipon;
  46.  
  47. NODEP glb_decls();
  48.  
  49. extern int oflags[];
  50. #define debugl oflags['l'-'a']
  51. #define debugs oflags['s'-'a']
  52. #define debugv oflags['v'-'a']
  53.  
  54. findtok(x)
  55. {
  56.     while (cur->e_token != EOFTOK && cur->e_token != x)
  57.         fadvnode();
  58.     if (cur->e_token == EOFTOK)
  59.         exit(1);
  60. }
  61.  
  62. extern NODEP symtab[];
  63.  
  64. program()
  65. {
  66.     NODEP last;
  67.  
  68.     skipon = 0;
  69. more:
  70.     last = glb_decls();
  71.     if (cur->e_token == EOFTOK)
  72.         return;
  73.     if (last) skipon = 0;   /* saw something valid */
  74.     if (last && last->n_tptr && last->n_tptr->t_token == '(') {
  75.     /* possible function definition */
  76.         if (debugs) {
  77.             printf("FUN ");
  78.             put_nnm(last);
  79.         }
  80.         out_fstart(last);
  81.         last->e_sc = K_EXTERN;
  82.         fun_start(last->n_tptr);
  83.         args_blk(last->n_tptr->n_right);
  84.         sub_block();
  85.         fun_end();
  86.         clr_lvl(); /* for args block */
  87.         goto more;
  88.     }
  89.     /* error if get to here */
  90.     if (last) {
  91.         error("missing ;");
  92.         goto more;
  93.     } else {
  94.         skip();
  95.         goto more;
  96.     }
  97. }
  98.  
  99. fun_start(np)
  100. NODEP np;
  101. {
  102.     NODEP functy();
  103.  
  104.     funtyp = functy(np);
  105.     curbrk = curcont = -1;
  106.     funtopl = new_lbl();
  107.     funbotl = new_lbl();
  108.     funretl = new_lbl();
  109.     switch (funtyp->t_token) {
  110.     case K_STRUCT:
  111.     case K_UNION:
  112.         funstrl = new_lbl();
  113.         break;
  114.     default:
  115.         funstrl = 0;
  116.     }
  117.     maxregs = 0;
  118.     maxlocs = 0;
  119.     out_br(funbotl);
  120.     def_lbl(funtopl);
  121. }
  122.  
  123. fun_end()
  124. {
  125.     NODEP np;
  126.  
  127.     if (labels) {
  128.         for (np = labels; np; np = np->n_next)
  129.             if (np->c_defined == 0)
  130.                 errorn("undefined label", np);
  131.         freenode(labels);
  132.         labels = NULL;
  133.     }
  134.     def_lbl(funretl);
  135.     out_fret(maxregs, funstrl);
  136.     def_lbl(funbotl);
  137.     out_fend(maxregs, maxlocs);
  138.     out_br(funtopl);
  139.     if (funstrl)
  140.         out_fs(funstrl, funtyp->t_size);
  141. }
  142.  
  143. skip()
  144. {
  145.     if (skipon == 0) {
  146.         error("syntax (try skipping...)");
  147.         skipon = 1;
  148.     }
  149.     fadvnode();
  150. }
  151.  
  152. block()
  153. {
  154.     int some;
  155.     int sawsome;
  156.  
  157.     some = loc_decls();
  158.     if (cur->e_token == EOFTOK)
  159.         return;
  160.     if (some) skipon = 0;
  161. more:
  162.     sawsome = stmts();
  163.     if (sawsome) skipon = 0;
  164.     if (cur->e_token == '}') {
  165.         if (blktab->b_regs > maxregs)
  166.             maxregs = blktab->b_regs;
  167.         if (blktab->b_size + blktab->b_tsize > maxlocs)
  168.             maxlocs = blktab->b_size + blktab->b_tsize;
  169.         return;
  170.     }
  171.  
  172.     /* error if get to here */
  173.     if (cur->e_token == EOFTOK || is_tykw(cur->e_token))
  174.         /* get out of block */
  175.         return;
  176.     else {
  177.         skip();
  178.         goto more;
  179.     }
  180. }
  181.  
  182. clr_lvl()
  183. {
  184.     NODE *bp;
  185.  
  186.     level--;
  187.     bp = blktab;
  188.     blktab = bp->n_next;
  189.     bp->n_next = NULL;
  190.     if (debugl && bp->b_syms) {
  191.         printf("local syms %d", level);
  192.         printlist(bp->b_syms);
  193.     }
  194.     freenode(bp->b_syms);
  195.     if (debugl && bp->b_tags) {
  196.         printf("local tags %d", level);
  197.         printlist(bp->b_tags);
  198.     }
  199.     freenode(bp->b_tags);
  200.     freenode(bp);
  201. }
  202.  
  203. eat(c)
  204. {
  205.     char *p = "assume X";
  206.  
  207.     if (cur->e_token == c)
  208.         fadvnode();
  209.     else {
  210.         p[strlen(p) - 1] = c;
  211.         error(p);
  212.     }
  213. }
  214.  
  215. sub_block()
  216. {
  217.     register NODE *new;
  218.  
  219.     if (debugs)
  220.         printf("{ ");
  221.     eat('{');
  222.     level++;
  223.     new = allocnode();
  224.     new->n_next = blktab;
  225.     sprintf(new->n_name, "sub{");
  226.     blktab = new;
  227.     block();
  228.     clr_lvl();
  229.     eat('}');
  230.     if (debugs)
  231.         printf("}\n");
  232. }
  233.  
  234. args_blk(np)
  235. NODEP np;
  236. {
  237.     register NODE *p;
  238.     register NODE *new;
  239.     NODE *tp;
  240.     NODEP llook();
  241.     long size;
  242.     int rmask;
  243.  
  244.     size = 0;
  245.     rmask = 0;
  246.     new = allocnode();
  247.     new->n_next = blktab;
  248.     sprintf(new->n_name, "arg{");
  249.     blktab = new;
  250.     level++;
  251.     loc_decls();
  252.     /* make sure all decls were in arg list */
  253.     for (p=new->b_syms; p != NULL; p = p->n_next)
  254.         if (llook(np, p) == NULL)
  255.             errorn("ID not param", p);
  256.     /* now make any names not mentioned INT */
  257.     /* and generate offsets and alloc regs */
  258.     for (p=np; p != NULL; p = p->n_next) {
  259.         if ((tp=llook(new->b_syms, p)) == NULL) {
  260.             def_arg(&new->b_syms, p);
  261.             tp = new->b_syms;
  262.         }
  263.         lc_size(&size, &rmask, tp);
  264.         if (tp->e_sc == K_REGISTER)
  265.             reg_arg(&rmask, tp);
  266.         if (debugv) {
  267.             printf("final o%ld r%d ", tp->e_offs, tp->e_rno);
  268.             put_nnm(tp);
  269.             putchar('\n');
  270.         }
  271.     }
  272.     new->b_regs = rmask;
  273. }
  274.  
  275. reg_arg(rp, xp)
  276. int *rp;
  277. NODEP xp;
  278. {
  279.     if (lc_reg(rp, xp) == 0) {      /* out of regs? */
  280.         xp->e_sc = K_AUTO;
  281.         return;
  282.     }
  283.     out_argreg(xp);
  284. }
  285.  
  286.  
  287. stmts()
  288. {
  289.     int didsome;
  290.  
  291.     didsome = 0;
  292.     while (stmt())
  293.         didsome++;
  294.     return didsome;
  295. }
  296.  
  297. stmt_bc(brk,cont)
  298. {
  299.     int svb, svc;
  300.  
  301.     svb = curbrk;
  302.     svc = curcont;
  303.     curbrk = brk;
  304.     curcont = cont;
  305.  
  306.     stmt();
  307.  
  308.     curbrk = svb;
  309.     curcont = svc;
  310. }
  311.  
  312. stmt_b(brk)
  313. {
  314.     int svb;
  315.  
  316.     svb = curbrk;
  317.     curbrk = brk;
  318.  
  319.     stmt();
  320.  
  321.     curbrk = svb;
  322. }
  323.  
  324. /* do a single statement */
  325. stmt()
  326. {
  327.     register tok;
  328.     NODEP np;
  329.     NODEP getexpr();
  330.     int i;
  331.  
  332. more:
  333.     tok = cur->e_token;
  334.     if (is_stkw(tok)) {
  335.         if (is_blkst(tok)) {
  336.             i = blk_stmt();
  337.         } else if (is_brast(tok)) {
  338.             i = bra_stmt();
  339.         } else if (is_lblst(tok)) {
  340.             i = lbl_stmt();
  341.         } else
  342.             i = asm_stmt();
  343.         if (i == 0)
  344.             goto more;
  345.         return 1;
  346.     }
  347.     else if (tok == '{') {
  348.         sub_block();
  349.         return 1;
  350.     } else if (tok == ';') {
  351.         fadvnode();
  352.         return 1;
  353.     }
  354.     np = getexpr();
  355.     if (np) {
  356.         if (cur->e_token == ':') {
  357.             fadvnode();
  358.             label(np);
  359.             goto more;
  360.         }
  361.         expr_stmt(np);
  362.         if (cur->e_token != ';')
  363.             error("missing ;");
  364.         else
  365.             fadvnode();
  366.         return 1;
  367.     }
  368.     return 0;
  369. }
  370.  
  371. expr_stmt(np)
  372. NODEP np;
  373. {
  374.     if (debugs) {
  375.         printf("E_STMT ");
  376.         if (debugs > 1)
  377.             printnode(np);
  378.     }
  379.     do_expr(np, FORSIDE);
  380. }
  381.  
  382. label(np)
  383. NODEP np;
  384. {
  385.     register NODEP tp;
  386.     NODEP llook();
  387.  
  388.     if (debugs) {
  389.         printf("LABEL ");
  390.         if (debugs > 1)
  391.             printnode(np);
  392.     }
  393.     if (np->e_token != ID) {
  394.         error("weird label");
  395.         return;
  396.     }
  397.     tp = llook(labels, np);
  398.     if (tp) {
  399.         freenode(np);
  400.         if (tp->c_defined) {
  401.             error("duplicate label");
  402.             return;
  403.         }
  404.     } else {
  405.         putlist(&labels, np);
  406.         tp = np;
  407.         tp->c_casel = new_lbl();
  408.     }
  409.     tp->c_defined = 1;
  410.     def_lbl(tp->c_casel);
  411. }
  412.  
  413.  
  414. extern int lineno;
  415.  
  416. blk_stmt()
  417. {
  418.     register tok;
  419.     int l1, l2, l3;
  420.     NODEP e1, e2, e3;
  421.     NODEP opt_expr(), paren_expr(), def_type();
  422.     struct swittbl locswit, *oldp;
  423.     int svline, svline2;
  424.  
  425.     tok = cur->e_token;
  426.     fadvnode();
  427.     switch (tok) {
  428.     case K_IF:
  429.         if (debugs)
  430.             printf("IF ");
  431.         l1 = new_lbl();
  432.         e1 = paren_expr();
  433.         gen_brf(e1, l1);
  434.         eat(')');
  435.         stmt();
  436.         opt_else(l1);
  437.         return 1;
  438.     case K_WHILE:
  439.         if (debugs)
  440.             printf("WHILE ");
  441.         e1 = paren_expr();
  442.         l1 = new_lbl();
  443.         l2 = new_lbl();
  444.  
  445.         def_lbl(l1);
  446.         gen_brf(e1,l2);
  447.         eat(')');
  448.  
  449.         stmt_bc(l2,l1);
  450.  
  451.         out_br(l1);
  452.         def_lbl(l2);
  453.         return 1;
  454.     case K_DO:
  455.         if (debugs)
  456.             printf("DO ");
  457.         l1 = new_lbl();
  458.         l2 = new_lbl();
  459.         l3 = new_lbl();
  460.         def_lbl(l1);
  461.  
  462.         stmt_bc(l3,l2);
  463.  
  464.         def_lbl(l2);
  465.         eat(K_WHILE);
  466.         e1 = paren_expr();
  467.         gen_brt(e1, l1);
  468.         eat(')');
  469.         eat(';');
  470.         def_lbl(l3);
  471.         return 1;
  472.     case K_FOR:
  473.         if (debugs)
  474.             printf("FOR ");
  475.         l1 = new_lbl();
  476.         l2 = new_lbl();
  477.         l3 = new_lbl();
  478.         eat('(');
  479.         e1 = opt_expr();
  480.         expr_stmt(e1);
  481.         eat(';');
  482.         def_lbl(l1);
  483.         e2 = opt_expr();
  484.         if (e2)
  485.             gen_brf(e2,l3);
  486.         eat(';');
  487.         e3 = opt_expr();        /* save for later */
  488.         svline = lineno;
  489.         eat(')');
  490.  
  491.         stmt_bc(l3,l2);
  492.  
  493.         def_lbl(l2);
  494.  
  495.         svline2 = lineno;
  496.         lineno = svline;
  497.         expr_stmt(e3);
  498.         lineno = svline2;
  499.  
  500.         out_br(l1);
  501.         def_lbl(l3);
  502.         return 1;
  503.     case K_SWITCH:
  504.         if (debugs)
  505.             printf("SWITCH ");
  506.         e1 = paren_expr();
  507.         l1 = new_lbl();
  508.         l2 = new_lbl();
  509.         to_d0(e1, def_type());
  510.         eat(')');
  511.  
  512.         out_br(l2);
  513.         oldp = curswit;
  514.         curswit = &locswit;
  515.         locswit.caselist = NULL;
  516.         locswit.deflbl = -1;
  517.  
  518.         stmt_b(l1);
  519.  
  520.         out_br(l1);
  521.         def_lbl(l2);
  522.         gen_switch(locswit.caselist, locswit.deflbl);
  523.         curswit = oldp;
  524.         def_lbl(l1);
  525.         return 1;
  526.     case K_ELSE:
  527.         error("unexpected 'else'");
  528.         fadvnode();
  529.         return 0;
  530.     }
  531. }
  532.  
  533. NODEP
  534. paren_expr()
  535. {
  536.     NODEP np;
  537.     NODEP need_expr();
  538.  
  539.     eat('(');
  540.     np = need_expr();
  541.     return np;
  542. }
  543.  
  544. bra_stmt()
  545. {
  546.     register tok;
  547.     NODEP np, tp;
  548.     NODEP opt_expr(), llook();
  549.  
  550.     tok = cur->e_token;
  551.     fadvnode();
  552.     switch (tok) {
  553.     case K_BREAK:
  554.         if (debugs)
  555.             printf("BRK");
  556.         eat(';');
  557.         out_br(curbrk);
  558.         return 1;
  559.     case K_CONTINUE:
  560.         if (debugs)
  561.             printf("CONT ");
  562.         eat(';');
  563.         out_br(curcont);
  564.         return 1;
  565.     case K_RETURN:
  566.         if (debugs)
  567.             printf("RETURN ");
  568.         np = opt_expr();
  569.         if (np) {
  570.             if (funstrl)
  571.                 ret_stru(np);
  572.             else
  573.                 to_d0(np, funtyp);
  574.         }
  575.         out_br(funretl);
  576.         eat(';');
  577.         return 1;
  578.     case K_GOTO:
  579.         if (debugs)
  580.             printf("GOTO ");
  581.         np = cur;  advnode();
  582.         if (np->e_token != ID)
  583.             error("bad goto");
  584.         else {
  585.             tp = llook(labels, np);
  586.             if (tp) {
  587.                 freenode(np);
  588.             } else {
  589.                 tp = np;
  590.                 putlist(&labels, tp);
  591.                 tp->c_casel = new_lbl();
  592.             }
  593.             out_br(tp->c_casel);
  594.         }
  595.         eat(';');
  596.         return 1;
  597.     }
  598. }
  599.  
  600. lbl_stmt()
  601. {
  602.     register tok;
  603.     NODEP need_expr(), np;
  604.     int l1, i;
  605.  
  606.     l1 = new_lbl();
  607.     tok = cur->e_token;
  608. again:
  609.     fadvnode();
  610.     switch (tok) {
  611.     case K_CASE:
  612.         if (debugs)
  613.             printf("CASE ");
  614.         np = need_expr();
  615.         i = conxval(np);
  616.         add_case(i,l1);
  617.         eat(':');
  618.         break;
  619.     case K_DEFAULT:
  620.         if (debugs)
  621.             printf("DEFAULT ");
  622.         if (curswit->deflbl >= 0)
  623.             error("multiple 'default'");
  624.         curswit->deflbl = l1;
  625.         eat(':');
  626.     }
  627.     tok = cur->e_token;    /* lookahead for more cases */
  628.     if (tok == K_CASE || tok == K_DEFAULT)
  629.         goto again;
  630.     def_lbl(l1);
  631.     return 0;
  632. }
  633.  
  634. asm_stmt()
  635. {
  636.     NODEP np, getexpr();
  637.  
  638.     fadvnode();
  639.     np = getexpr();
  640.     if (np == NULL || np->e_token != SCON) {
  641.         error("bad asm() func");
  642.     } else {
  643.         out_asm(np);
  644.         freenode(np);
  645.     }
  646.     eat(';');
  647. }
  648.  
  649. NODEP
  650. opt_expr()
  651. {
  652.     NODE *np, *getexpr();
  653.  
  654.     np = getexpr();
  655.     if (np) {
  656.         if (debugs) {
  657.             printf("OXPR ");
  658.             if (debugs > 1)
  659.                 printnode(np);
  660.         }
  661.     }
  662.     return np;
  663. }
  664.  
  665. NODEP
  666. need_expr()
  667. {
  668.     NODE *np, *getexpr();
  669.  
  670.     np = getexpr();
  671.     if (np) {
  672.         if (debugs) {
  673.             printf("NXPR ");
  674.             if (debugs > 1)
  675.                 printnode(np);
  676.         }
  677.     } else
  678.         error("need expr");
  679.     return np;
  680. }
  681.  
  682. opt_else(l1)
  683. {
  684.     int l2;
  685.  
  686.     if (cur->e_token == K_ELSE) {
  687.         if (debugs)
  688.             printf("ELSE ");
  689.         fadvnode();
  690.         l2 = new_lbl();
  691.         out_br(l2);
  692.         def_lbl(l1);
  693.         stmt();
  694.         def_lbl(l2);
  695.     } else
  696.         def_lbl(l1);
  697. }
  698.  
  699. add_case(val, lbl)
  700. {
  701.     NODEP np, last, p;
  702.  
  703.     np = allocnode();
  704.     np->c_casev = val;
  705.     np->c_casel = lbl;
  706.     sprintf(np->n_name, "%d:%d", val, lbl);
  707.  
  708.     last = NULL;
  709.     for (p = curswit->caselist; p; last=p, p=p->n_next)
  710.         if (p->c_casev == val) {
  711.             error("duplicate case");
  712.             return;
  713.         } else if (p->c_casev > val)
  714.             break;
  715.     if (last) {
  716.         last->n_next = np;
  717.         np->n_next = p;
  718.     } else {
  719.         curswit->caselist = np;
  720.         np->n_next = p;
  721.     }
  722.     if (debugs) {
  723.         printf("CASELIST\n");
  724.         printnode(curswit->caselist);
  725.     }
  726. }
  727.  
  728. to_d0(np, typ)
  729. NODEP np, typ;
  730. {
  731.     NODEP tp;
  732.  
  733.     tp = allocnode();
  734.     tp->e_token = TCONV;
  735.     tp->n_tptr = typ;
  736.     tp->n_flags |= N_COPYT;
  737.     tp->n_left = np;
  738.     tp->e_type = E_UNARY;
  739.     strcpy(tp->n_name, "r cast");
  740.  
  741.     do_expr(tp, IND0);
  742. }
  743.  
  744. ret_stru(np)
  745. NODEP np;
  746. {
  747.     p2_expr(&np);
  748.     if (same_type(np->n_tptr, funtyp) == 0) {
  749.         error("bad struct return type");
  750.         return;
  751.     }
  752.     genx(np, RETSTRU);
  753. }
  754.